﻿
using AutojsController.Config;
using AutojsController.Helpers;
using AutojsController.Services;
using Avalonia.Input;
using Avalonia.Layout;
using Microsoft.VisualBasic;
using ReactiveUI;
using Serilog;
using SukiUI.Dialogs;
using SukiUI.Toasts;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Input;
using Tmds.DBus.Protocol;

namespace AutojsController.ViewModels
{
    public class GroupedMobiles:INotifyPropertyChanged
    {
        public string GroupName { get; set; } = null!;
        public int GroupId { get; set; }
        private Script? _script;
        public Script? Script
        {
            get => _script;
            set
            {
                if (_script?.Id != value?.Id)
                {
                    _script = value;
                    OnPropertyChanged(nameof(this.Script));
                }
            }
        }
        public ObservableCollection<MobileItemViewModel> Mobiles { get; set; } = new();
        public event PropertyChangedEventHandler? PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class GroupViewModel : ViewModelBase
    {
        private readonly ISukiDialogManager dialogManager;
        private readonly ISukiToastManager toastManager;
        private readonly MobilesService mobservice;
        private readonly GroupsService grpservice;
        public ObservableCollection<GroupedMobiles> MobileGroups { get; set; } = new();
        public ObservableCollection<MobileItemViewModel> UngroupedMobiles { get; set; } = new();

        private int selectedIndex = 0;
        public int TabControlSelectedIndex
        {
            get => selectedIndex;
            set => this.RaiseAndSetIfChanged(ref selectedIndex, value);
        }

        public ICommand AddGroupCommand => ReactiveCommand.Create(addGroup);
        public ICommand RenameGroupCommand => ReactiveCommand.CreateFromTask<int>(renameGroupAsync);
        public ICommand DeleteGroupCommand => ReactiveCommand.CreateFromTask<int>(deleteGroupAsync);
        public ICommand RemoveMobilesCommand => ReactiveCommand.CreateFromTask<int>(removeMobilesFromGroupAsync);
        private readonly ILogger logger = LoggerFactory.GetLogger();

        public GroupViewModel(ISukiDialogManager dlgmanager, ISukiToastManager toastmanager, MobilesService mobservice, GroupsService grpservice) : base("分组管理", Material.Icons.MaterialIconKind.FormatListGroup, 20)
        {
            this.dialogManager = dlgmanager;
            this.toastManager = toastmanager;
            this.mobservice = mobservice;
            this.grpservice = grpservice;
            RefreshGroupsAsync().Wait();
            mobservice.MobileItems.CollectionChanged += async (_, _) => await RefreshGroupsAsync();
        }

        /// <summary>
        /// TODO:效率略低，需要优化，在已加载过后不使用清空再添加
        /// </summary>
        /// <returns></returns>
        public async Task RefreshGroupsAsync()
        {
            MobileGroups.Clear();
            UngroupedMobiles.Clear();
            var groups = await grpservice.getAllGroupsAsync();
            foreach (var group in groups)
            {
                var groupedMobiles = mobservice.MobileItems.Where(m => m.Mobile.GroupId == group.Id);
                MobileGroups.Add(new GroupedMobiles
                {
                    GroupName = group.Name,
                    GroupId = group.Id,
                    Script = group.Script,
                    Mobiles = new ObservableCollection<MobileItemViewModel>(groupedMobiles)
                });
            }
            var ungrouped = mobservice.MobileItems.Where(m => m.Mobile.GroupId == 0 || m.Mobile.GroupId == null);
            foreach (var mobile in ungrouped)
            {
                UngroupedMobiles.Add(mobile);
            }
            //this.RaisePropertyChanged(nameof(MobileGroups));
            //this.RaisePropertyChanged(nameof(UngroupedMobiles));
        }

        public void SelectMobileOrNot(MobileItemViewModel mobile)
        {
            if (mobile.IsSelected)
            {
                mobile.IsSelected = false;
            }
            else
            {
                mobile.IsSelected = true;
                var mobileGroupId = mobile.Mobile.GroupId;
                foreach (var _mobile in this.mobservice.MobileItems)
                {
                    if (_mobile.Mobile.GroupId != mobileGroupId)
                    {
                        _mobile.IsSelected = false;
                    }
                }
            }
        }

        private void addGroup()
        {
            var dialog = dialogManager.CreateDialog().ShowCardBackground(true);
            var vm = new AddOrRenameGroupDialogViewModel(dialog.Dialog, toastManager, null, grpservice);
            dialog.WithViewModel(_ => vm).TryShow();
            vm.Closed += async (changed) => await saveGroupChangeAsync(-1, changed);
        }

        private async Task renameGroupAsync(int grpIndex)
        {
            var grp = await grpservice.GetByGroupIdAsync(MobileGroups[grpIndex].GroupId);
            var dialog = dialogManager.CreateDialog().ShowCardBackground(true);
            var vm = new AddOrRenameGroupDialogViewModel(dialog.Dialog, toastManager, grp, grpservice);
            dialog.WithViewModel(_ => vm).TryShow();
            vm.Closed += async (changed) => await saveGroupChangeAsync(grpIndex, changed);
        }

        private async Task saveGroupChangeAsync(int currentIndex, bool changed)
        {
            if (changed)
            {
                await RefreshGroupsAsync();
            }
            TabControlSelectedIndex = currentIndex < 0 ? MobileGroups.Count() - 1 : currentIndex;
        }

        public async Task AddMobilesToGroupAsync(List<MobileItemViewModel> mobiles, int grpId)
        {
            if (mobiles.Count == 0)
                return;
            foreach (var mobile in mobiles)
            {
                var _mobile = await mobservice.AddMobileToGroup(mobile.Mobile.Id, grpId);
                if (_mobile != null)
                {
                    logger.Information($"将设备{_mobile.Address}添加到分组{MobileGroups.FirstOrDefault(g => g.GroupId == grpId)?.GroupName}");
                    mobile.Mobile = _mobile;
                }
            }
            await RefreshGroupsAsync();
        }

        private async Task deleteGroupAsync(int grpIndex)
        {
            var grpMobiles = MobileGroups[grpIndex].Mobiles;
            if (grpMobiles.Count != 0) SukiToast.Error(toastManager, "清空该分组设备后才可以删除", 3);
            else await grpservice.DeleteGroupAsync(MobileGroups[grpIndex].GroupId);
            logger.Information($"删除分组{MobileGroups[grpIndex].GroupName}");
            await RefreshGroupsAsync();
            this.TabControlSelectedIndex = grpIndex - 1;
        }

        private async Task removeMobilesFromGroupAsync(int grpIndex)
        {
            var grpId = MobileGroups[grpIndex].GroupId;
            foreach(var mobile in MobileGroups[grpIndex].Mobiles.Where(m=>m.IsSelected))
            {
                if (mobile.Status == MobileStatus.Running)
                {
                    SukiToast.Info(toastManager, $"{mobile.Mobile.Address}运行中不可移除");
                    continue;
                }
                await mobservice.RemoveMobileFromGroupAsync(mobile.Mobile.Id, grpId);
                logger.Information($"将设备{mobile.Mobile.Address}从分组{MobileGroups[grpIndex].GroupName}中移除");
            }
            await RefreshGroupsAsync();
        }
    }
}
